#pragma once
#include "snetwork/NluHttpRequest.h"
#include "Sock.h"
#include "ado/DbMysql.h"
#include "snetwork/NluConnection.h"

/*
 * The event filter requires to read/write the whole data:
 * select, poll, /dev/poll, kqueue, epoll.
 */
#define HTTP_USE_LEVEL_EVENT      0x00000001

/*
 * The event filter is deleted after a notification without an additional
 * syscall: kqueue, epoll.
 */
#define HTTP_USE_ONESHOT_EVENT    0x00000002

/*
 * The event filter notifies only the changes and an initial level:
 * kqueue, epoll.
 */
#define HTTP_USE_CLEAR_EVENT      0x00000004

/*
 * The event filter has kqueue features: the eof flag, errno,
 * available data, etc.
 */
#define HTTP_USE_KQUEUE_EVENT     0x00000008

/*
 * The event filter supports low water mark: kqueue's NOTE_LOWAT.
 * kqueue in FreeBSD 4.1-4.2 has no NOTE_LOWAT so we need a separate flag.
 */
#define HTTP_USE_LOWAT_EVENT      0x00000010

/*
 * The event filter requires to do i/o operation until EAGAIN: epoll, rtsig.
 */
#define HTTP_USE_GREEDY_EVENT     0x00000020

/*
 * The event filter is epoll.
 */
#define HTTP_USE_EPOLL_EVENT      0x00000040

/*
 * No need to add or delete the event filters: rtsig.
 */
#define HTTP_USE_RTSIG_EVENT      0x00000080

/*
 * No need to add or delete the event filters: overlapped, aio_read,
 * aioread, io_submit.
 */
#define HTTP_USE_AIO_EVENT        0x00000100

/*
 * Need to add socket or handle only once: i/o completion port.
 * It also requires NGX_HAVE_AIO and NGX_USE_AIO_EVENT to be set.
 */
#define HTTP_USE_IOCP_EVENT       0x00000200

/*
 * The event filter has no opaque data and requires file descriptors table:
 * poll, /dev/poll, rtsig.
 */
#define HTTP_USE_FD_EVENT         0x00000400

/*
 * The event module handles periodic or absolute timer event by itself:
 * kqueue in FreeBSD 4.4, NetBSD 2.0, and MacOSX 10.4, Solaris 10's event ports.
 */
#define HTTP_USE_TIMER_EVENT      0x00000800

/*
 * All event filters on file descriptor are deleted after a notification:
 * Solaris 10's event ports.
 */
#define HTTP_USE_EVENTPORT_EVENT  0x00001000

/*
 * The event filter support vnode notifications: kqueue.
 */
#define HTTP_USE_VNODE_EVENT      0x00002000


/*
 * The event filter is deleted just before the closing file.
 * Has no meaning for select and poll.
 * kqueue, epoll, rtsig, eventport:  allows to avoid explicit delete,
 *                                   because filter automatically is deleted
 *                                   on file close,
 *
 * /dev/poll:                        we need to flush POLLREMOVE event
 *                                   before closing file.
 */
#define HTTP_CLOSE_EVENT    1

/*
 * disable temporarily event filter, this may avoid locks
 * in kernel malloc()/free(): kqueue.
 */
#define HTTP_DISABLE_EVENT  2

/*
 * event must be passed to kernel right now, do not wait until batch processing.
 */
#define HTTP_FLUSH_EVENT    4


/* these flags have a meaning only for kqueue */
#define HTTP_LOWAT_EVENT    0
#define HTTP_VNODE_EVENT    0


#if (NGX_HAVE_KQUEUE)

#define HTTP_READ_EVENT     EVFILT_READ
#define HTTP_WRITE_EVENT    EVFILT_WRITE

#undef  NGX_VNODE_EVENT
#define HTTP_VNODE_EVENT    EVFILT_VNODE

/*
 * NGX_CLOSE_EVENT, NGX_LOWAT_EVENT, and NGX_FLUSH_EVENT are the module flags
 * and they must not go into a kernel so we need to choose the value
 * that must not interfere with any existent and future kqueue flags.
 * kqueue has such values - EV_FLAG1, EV_EOF, and EV_ERROR:
 * they are reserved and cleared on a kernel entrance.
 */
#undef  NGX_CLOSE_EVENT
#define HTTP_CLOSE_EVENT    EV_EOF

#undef  NGX_LOWAT_EVENT
#define HTTP_LOWAT_EVENT    EV_FLAG1

#undef  NGX_FLUSH_EVENT
#define HTTP_FLUSH_EVENT    EV_ERROR

#define HTTP_LEVEL_EVENT    0
#define HTTP_ONESHOT_EVENT  EV_ONESHOT
#define HTTP_CLEAR_EVENT    EV_CLEAR

#undef  NGX_DISABLE_EVENT
#define HTTP_DISABLE_EVENT  EV_DISABLE


#elif (NGX_HAVE_DEVPOLL || NGX_HAVE_EVENTPORT)

#define HTTP_READ_EVENT     POLLIN
#define HTTP_WRITE_EVENT    POLLOUT

#define HTTP_LEVEL_EVENT    0
#define HTTP_ONESHOT_EVENT  1


#elif (NGX_HAVE_EPOLL)

#define HTTP_READ_EVENT     EPOLLIN
#define HTTP_WRITE_EVENT    EPOLLOUT

#define HTTP_LEVEL_EVENT    0
#define HTTP_CLEAR_EVENT    EPOLLET
#define HTTP_ONESHOT_EVENT  0x70000000
#if 0
#define HTTP_ONESHOT_EVENT  EPOLLONESHOT
#endif


#elif (NGX_HAVE_POLL)

#define HTTP_READ_EVENT     POLLIN
#define HTTP_WRITE_EVENT    POLLOUT

#define HTTP_LEVEL_EVENT    0
#define HTTP_ONESHOT_EVENT  1


#else /* select */

#define HTTP_READ_EVENT     0
#define HTTP_WRITE_EVENT    1

#define HTTP_LEVEL_EVENT    0
#define HTTP_ONESHOT_EVENT  1

#endif /* NGX_HAVE_KQUEUE */


#if (NGX_HAVE_IOCP)
#define HTTP_IOCP_ACCEPT      0
#define HTTP_IOCP_IO          1
#define HTTP_IOCP_CONNECT     2
#endif


#ifndef NGX_CLEAR_EVENT
#define HTTP_CLEAR_EVENT    0    /* dummy declaration */
#endif



#define HTTP_EVENT_MODULE      0x544E5645  /* "EVNT" */
#define HTTP_EVENT_CONF        0x02000000


#define     HEADER_INIT_LEN     2048

extern unsigned int http_event_flags;
extern int n_epfd;

//for event
typedef struct {
    void            *data;
    unsigned         write:1;
    unsigned         accept:1;

    /* used to detect the stale events in kqueue, rtsig, and epoll */
    unsigned         instance:1;

    /*
     * the event was passed or would be passed to a kernel;
     * in aio mode - operation was posted.
     */
    unsigned         active:1;
    unsigned         disabled:1;

    /* the ready event; in aio mode 0 means that no operation can be posted */
    unsigned         ready:1;
    unsigned         oneshot:1;
    
    unsigned         closed:1;

    /* to test on worker exit */
    unsigned         channel:1;
    unsigned         resolver:1;

    /* aio operation is complete */
    unsigned         complete:1;
    unsigned         eof:1;
    unsigned         error:1;
    unsigned         timedout:1;
    unsigned         timer_set:1;
    unsigned         delayed:1;
    unsigned         read_discarded:1;
    unsigned         unexpected_eof:1;
    unsigned         deferred_accept:1;
} nlu_event_t;

typedef nlu_event_t nl_event_t;

class SNETWORK_API Sock::CNluEvent {
public:
    static CNluEvent *instance();
    CNluEvent();
    int handleInit(nlu_cycle_t *cycle);
    void execute(nlu_cycle_t *cycle);
    void handleProcess(void *tevent, ssize_t* cnt_len);
    void handleAccept(struct epoll_event* pEvent);    
    void HttpInitEvent(nl_http_request_t *r);
    void HttpCloseEvent(nl_http_request_t *r);
	int setnonblocking(int sockfd);
	            
protected:    
    //struct epoll_event m_ev;
    struct epoll_event *m_event_list;
    nlu_pool_t *m_request_pool;
    paramArr m_tparr;
    paramArr *m_parr;
    int m_epfd;
    MYSQL* m_mysql_conn;
    tDataBase m_db;	
    fd_set m_rfdsr;
    fd_set m_wfdsr;
    static CNluEvent* m_instance;    
    class CGarbo {public: ~CGarbo(){if (CNluEvent::m_instance) delete CNluEvent::m_instance;}};
    static CGarbo Garbo;       
};
